//
//  ZYLoadingProgress.m
//  CALayerAnimation
//
//  Created by linziyuan on 16/4/20.
//  Copyright © 2016年 creative. All rights reserved.
//

#import "ZYLoadingProgress.h"

@interface ZYLoadingProgress ()

@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@property (nonatomic, assign) BOOL isAnimating;
/** Progress Value (0~1) */
@property (nonatomic, assign) CGFloat progressValue;
/**路径*/
@property (nonatomic, strong) UIBezierPath *path;
//
@property (nonatomic, strong) NSTimer *timer;

@end

@implementation ZYLoadingProgress
{
    BOOL _isFirstLoad;
}
//将UIView默认的CALayer替换成CAGradientLayer
+(Class)layerClass {
    return [CAGradientLayer class];
}

- (instancetype)init {
    return [self initWithFrame:CGRectZero];
}

- (instancetype)initWithFrame:(CGRect)frame {
    return [self initWithFrame:frame colors:nil];
}

- (instancetype)initWithFrame:(CGRect)frame colors:(NSArray <UIColor*> *)colors{
    self = [super initWithFrame:frame];
    if (self) {
        if (frame.size.width < 1) {
            self.frame = CGRectMake(0, 44,[UIScreen mainScreen].bounds.size.width, 2);
        }
        [self setUpColorLayerColors:colors];
        self.progressValue = 0.0;
        self.colorMove = YES;
    }
    return self;
}

- (void)setUpColorLayerColors:(NSArray <UIColor*> *)colors {
    //创建CAGradientlayer
    CAGradientLayer* gradientLayer = (CAGradientLayer*)self.layer;
    [gradientLayer setStartPoint:CGPointMake(0, 0)];
    [gradientLayer setEndPoint:CGPointMake(1, 0)];
    
    //创建遮罩层(CAShapeLayer)需要配合bezierPath
    UIBezierPath* shapePath = [UIBezierPath bezierPath];
    [shapePath moveToPoint:CGPointMake(0, 0)];
    [shapePath addLineToPoint:CGPointMake(self.frame.size.width, 0)];
    
    CAShapeLayer *shapeMaskLayer = [CAShapeLayer layer];
    shapeMaskLayer.path = shapePath.CGPath;
    shapeMaskLayer.lineWidth = 4.f;
    shapeMaskLayer.fillColor = [UIColor clearColor].CGColor;
    shapeMaskLayer.strokeColor = [UIColor blackColor].CGColor;
    // 设置shapeMaskLayer的起止点初始值均为0
    shapeMaskLayer.strokeStart = 0;
    shapeMaskLayer.strokeEnd = 0;
    
    self.gradientLayer = gradientLayer;
    self.gradientLayer.mask = shapeMaskLayer;
    self.colors = colors;
    self.shapeLayer = shapeMaskLayer;
}
//关于Layer的mask属性 [Check this blog Fun With CALayer Mask](http://blog.zhowkev.in/2015/07/06/fun-with-mask/)

- (void)startAnimating {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startAnimating) object:nil];
    if (!self.isAnimating && self.progressValue == 0) {
        self.isAnimating = YES;
        if(self.colorMove)[self performAnimation];
        self.alpha = 1.0;
        self.hidden = NO;
        self.progressValue = 0.2;
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(strokePath) userInfo:nil repeats:YES];
    }else if(!self.isAnimating){
        [self performSelector:@selector(startAnimating) withObject:nil afterDelay:0.33];
    }
}

- (void)stopAnimating {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startAnimating) object:nil];
    if (self.isAnimating) {
        [self.timer invalidate];
        self.timer = nil;
        self.progressValue = 1.0;
        self.isAnimating = NO;
        [UIView animateWithDuration:0.6 animations:^{
            self.alpha = 0.0;
        } completion:^(BOOL finished) {
            self.hidden  = YES;
            self.progressValue = 0;
        }];
    }
}

- (void)strokePath {
    self.progressValue = self.progressValue +  (arc4random() % 80 / 150.f + 0.1);
    if (self.progressValue >= 0.95) {
        self.progressValue = 0.95;
    }
}

- (void)performAnimation {
    
    CAGradientLayer *layer = (id)[self layer];
    if ([layer colors].count > 1) {
        NSArray *fromColors = [layer colors];
        NSArray *toColors = [self shiftColors:fromColors];
        [layer setColors:toColors];
        CGFloat duaration = 0.08;
        duaration = (CGFloat)(120*0.08) / (CGFloat)fromColors.count;
        CABasicAnimation *animation;
        animation = [CABasicAnimation animationWithKeyPath:@"colors"];
        [animation setFromValue:fromColors];
        [animation setToValue:toColors];
        [animation setDuration:duaration];                   // CALayer的color切换时间
        [animation setRemovedOnCompletion:YES];         // 动画完成后是否要移除
        [animation setFillMode:kCAFillModeForwards];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
        [animation setDelegate:self];
        
        // Add the animation to our layer
        //[layer addAnimation:animation forKey:@"animateGradient"];
    }
}

 - (NSArray *)shiftColors:(NSArray *)colors {
     // 数组中最后一项移动到前面
     // 转移的所有其他元素
     NSMutableArray *mutable = [colors mutableCopy];// 将NSArray数组换成 NSMutableArray
     id last = [mutable lastObject]; // 单独取出最后一个元素
     [mutable removeLastObject];              // 然后将数组中的最后一个元素去除
     [mutable insertObject:last atIndex:0];   // 然后将取出的元素插入到最前面
     return [NSArray arrayWithArray:mutable];
}

#pragma mark CABasicAnimationDelegate
/*
 当动画在活动时间内完成或者是从层对象中移除这个代理方法会被调用，如果动画直到它的活动时间末尾没有被移除，那这个'flag'是true的。
 回调和布尔值来保证动画的循环开始并持续以及结束该动画
 */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    // 当动画在duration时间结束前移除了，这个方法会被调用
    // 然后就下面的if语句判断，如果isAnimation = yes，就重新执行performAnimation
    // 在这个performAnimation中重新创建了核心动画对象，重新设置了代理
    if ([self isAnimating]) {
        [self performAnimation];
    }
}

- (void)layoutSubviews {
    [super layoutSubviews];
    CGRect frame = self.frame;
    self.frame = frame;
}

#pragma mark set && get
@synthesize progressValue = _progressValue;
- (void)setProgressValue:(CGFloat)progressValue {
    progressValue = progressValue > 1 ? 1 : progressValue;
    progressValue = progressValue < 0 ? 0 : progressValue;
    _progressValue = progressValue;
    self.shapeLayer.strokeEnd = _progressValue;
}

-(CGFloat)progressValue{
    return _progressValue;
}

@synthesize colors = _colors;
- (void)setColors:(NSArray<UIColor *> *)colors {
    
    NSMutableArray *rainBowColors = [NSMutableArray array];
    if (colors.count > 0) {
        NSMutableArray *fillArr = [NSMutableArray arrayWithArray:colors];
        if (colors.count < 2) {
            [fillArr addObject:colors[0]];
        }
        for (UIColor *colorItem in fillArr) {
            id layercolor = (__bridge id)colorItem.CGColor;
            [rainBowColors addObject:layercolor];
        }
    }else {
        for (NSInteger hue = 0; hue <= 360; hue += 5) {
            UIColor *color = [UIColor colorWithHue:1.0*hue/360.0
                                        saturation:1.0
                                        brightness:1.0
                                             alpha:1.0];
            [rainBowColors addObject:(id)color.CGColor];
        }
    }
    _colors = colors;
    self.gradientLayer.colors = [NSArray arrayWithArray:rainBowColors];
}

- (NSArray<UIColor *> *)colors {
    return _colors;
}

@synthesize path = _path;
-(void)setPath:(UIBezierPath *)path{
    _path = path;
    _shapeLayer.frame = _path.bounds;
    _shapeLayer.path = _path.CGPath;
}
-(UIBezierPath *)path{
    return _path;
}

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    UIBezierPath* shapePath = [UIBezierPath bezierPath];
    [shapePath moveToPoint:CGPointMake(0, 0)];
    [shapePath addLineToPoint:CGPointMake(frame.size.width, 0)];
    self.path = shapePath;
    int scaleValue = [[UIScreen mainScreen] scale];
    self.shapeLayer.lineWidth = frame.size.height*scaleValue;
}
- (CGRect)frame {
    return  [super frame];
}

@end
